#include<windows.h>
#include<stdio.h>
#include<winioctl.h>
#include<commctrl.h>
#include"resource.h"

#pragma comment( lib , "comctl32.lib" )

//
// desription of a new device
// 
typedef struct _NEW_DEVICE
{
	WCHAR DeviceName[1024];
	WCHAR PDOName[1024];
} NEW_DEVICE , *PNEW_DEVICE;

//
// icotl codes
//
#define IOCTL_APP_INIT CTL_CODE(FILE_DEVICE_UNKNOWN , 0x806 , METHOD_BUFFERED , FILE_ANY_ACCESS)
#define IOCTL_APP_EXIT CTL_CODE(FILE_DEVICE_UNKNOWN , 0x807 , METHOD_BUFFERED , FILE_ANY_ACCESS)
#define IOCTL_APP_GET  CTL_CODE(FILE_DEVICE_UNKNOWN , 0x808 , METHOD_BUFFERED , FILE_ANY_ACCESS)

HANDLE hDevice;
HANDLE hThread;
HANDLE hEvent;
LV_COLUMN lvc;
LV_ITEM lvi;
BOOL is_actual;
HWND hList;
SC_HANDLE _scm;

BOOL StopDriver(SC_HANDLE scm , LPCTSTR DriverName)
{
	SC_HANDLE Service = OpenService(scm , DriverName , SERVICE_ALL_ACCESS);
	if(Service == NULL)
	{
		MessageBox(NULL,"Error Can't stop driver!","Error:", MB_ICONERROR);
		return FALSE;
	}
	SERVICE_STATUS  serviceStatus;
	BOOL ret = ControlService(Service , SERVICE_CONTROL_STOP , &serviceStatus);
	if(!ret)
	{
		DWORD err = GetLastError();
	}
	CloseServiceHandle(Service);
	return ret;
}

BOOL StartDriver(SC_HANDLE scm , LPCTSTR DriverName)
{
	SC_HANDLE Service = OpenService(scm , DriverName , SERVICE_ALL_ACCESS);
	if( Service == NULL )
	{
		MessageBox(NULL,"Can't Open Service!","Error", MB_ICONERROR);
	}
    BOOL ret = StartService(Service , 0 , NULL);
	if(!ret)
	{
		DWORD err = GetLastError( );
		if( err == ERROR_SERVICE_ALREADY_RUNNING )
		{
			MessageBox(NULL,"Service all ready running!","Information", MB_ICONERROR);
			ret = TRUE;
		}
		else
		{
			MessageBox(NULL,"Can't Start Driver","Error!", MB_ICONERROR);
		}
	}
		CloseServiceHandle(Service);
		return ret;
}

BOOL InstallDriver(SC_HANDLE scm , LPCTSTR DriverName , LPCTSTR DriverPath)
{
	SC_HANDLE Service = CreateService(scm , 
		                              DriverName ,
									  DriverName ,
									  SERVICE_ALL_ACCESS,
									  SERVICE_KERNEL_DRIVER ,
									  SERVICE_DEMAND_START ,
									  SERVICE_ERROR_IGNORE ,
									  DriverPath,
									  NULL,
									  NULL,
									  NULL,
									  NULL,
									  NULL);
	if(Service == NULL)
	{
		DWORD err = GetLastError( );
		if( err == ERROR_SERVICE_EXISTS ) /* service allready started*/
		{
	//		MessageBox(NULL,"Service Allready Started!","Information",  MB_ICONINFORMATION);
		}
		else
		{
			MessageBox(NULL,"Can't Start Service!","Error!",  MB_ICONERROR);
		
		}
		return FALSE;
	}
	    CloseServiceHandle(Service);
		return TRUE;
}

VOID AddDeviceInfo( PNEW_DEVICE pdev )
{
	char TempBuff[1024];

	lvi.iItem = 0;
	lvi.iSubItem = 0;
	wcstombs( TempBuff , pdev->DeviceName  , 1024 );
	lvi.pszText = TempBuff;
	ListView_InsertItem( hList , &lvi );
    wcstombs( TempBuff , pdev->PDOName , 1024 );
	ListView_SetItemText( hList , 0 , 1 , TempBuff );
}

DWORD WINAPI ThreadRoutine( LPVOID lpParam )
{
	DWORD err;
	NEW_DEVICE new_dev;
	DWORD err_req;
	DWORD ret;
	while( is_actual == TRUE )
	{
		err = WaitForSingleObject( hEvent , INFINITE );
		if( err == WAIT_FAILED )
		{
			MessageBox( NULL , "Error in Thread!" , "Error:" , MB_ICONERROR );
			break;
		}
		memset( &new_dev , 0 , sizeof(new_dev) );
		err_req = DeviceIoControl( hDevice , IOCTL_APP_GET , NULL , NULL , &new_dev , sizeof(new_dev) , &ret , 0 );
		if( !err_req )
		{
			MessageBox( NULL , "Can't Get Data from Driver!" , "Error:" , MB_ICONERROR );
		}
		else AddDeviceInfo( &new_dev );

	}
	return 0;
}

int WINAPI SpyDialogProc( HWND hWnd , UINT msg , WPARAM wp , LPARAM lp )
{
	DWORD err;
	DWORD Ret;
	HICON hIcon;
	RECT  Rect;
	if( msg == WM_INITDIALOG )
	{
		InitCommonControls( );
		hList = GetDlgItem( hWnd , IDC_LIST1 );
		//
		// making columns
		//
		memset( &lvc , 0 , sizeof(lvc) );
		memset( &lvi , 0 , sizeof(lvi) );
		lvc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT | LVCF_SUBITEM;
		lvc.fmt = LVCFMT_LEFT;
		lvc.iSubItem = 0;
		lvc.cx = 150;
		lvc.pszText = "Device Name";
		ListView_InsertColumn( hList , 0 , &lvc );
		lvc.pszText = "PDO Name";
		ListView_InsertColumn( hList , 1 , &lvc );
		ListView_SetExtendedListViewStyle( hList, LVS_EX_GRIDLINES + LVS_EX_FULLROWSELECT );
		lvi.mask = LVIF_IMAGE | LVIF_TEXT | LVIF_PARAM;
		hIcon = LoadIcon( GetModuleHandle(NULL) , MAKEINTRESOURCE(IDI_ICON1) );
		SendMessage( hWnd , WM_SETICON , ICON_BIG , (LPARAM)hIcon );
		GetClientRect( hWnd, &Rect );
		MoveWindow( hWnd , Rect.left , Rect.top , Rect.right , Rect.bottom , FALSE );

	}
	if( msg == WM_SIZE )
	{
	   MoveWindow( hList , 0 , 0 , LOWORD(lp) , HIWORD(lp) , TRUE );
	}

	if( msg == WM_CLOSE )
	{
		is_actual = FALSE;
		err = DeviceIoControl( hDevice , IOCTL_APP_EXIT , NULL , NULL , NULL , NULL , &Ret , NULL );
		if( !err )
		{
			MessageBox( hWnd , "Can't Send Reuqest to driver!" , "Error:" , MB_ICONERROR );
		}
		CloseHandle( hDevice );
		CloseHandle( hEvent );
		StopDriver( _scm , "susb_spy" );
		EndDialog( hWnd , 0 );
	}
	return 0;
}

int WINAPI WinMain( HINSTANCE , HINSTANCE , LPSTR , int )
{
	char DriverPath[1024];
	DWORD err;
	DWORD thread_id;
	DWORD Ret;
    
	is_actual = TRUE;
	GetCurrentDirectory( 1024 , DriverPath );
	strcat( DriverPath , "\\usb_spy.sys" );
	hEvent = CreateEvent( NULL , FALSE , FALSE , NULL );
	if( hEvent == NULL )
	{
		MessageBox( NULL , "Can't Create event!" , "Error:" , MB_ICONERROR );
		return 0;
	}
	hThread = CreateThread( NULL , NULL , ThreadRoutine , NULL , NULL , &thread_id );
	if( hThread == NULL )
	{
		MessageBox( NULL , "Can't Create Thread!" , "Error:" , MB_ICONERROR );
		return 0;
	}
	 _scm = OpenSCManager( NULL , NULL , SC_MANAGER_ALL_ACCESS );
	InstallDriver( _scm , "susb_spy" , DriverPath );
    StartDriver( _scm , "susb_spy" );
	hDevice = CreateFile ( "\\\\.\\susb_spy" , GENERIC_READ | GENERIC_WRITE , FILE_SHARE_READ | FILE_SHARE_WRITE , NULL , OPEN_EXISTING , FILE_ATTRIBUTE_NORMAL , NULL );
	if( hDevice == INVALID_HANDLE_VALUE )
	{
		MessageBox( NULL , "Can't Communicate With Driver!" , "Error:" , MB_ICONERROR );
		return 0;
	}
	err = DeviceIoControl( hDevice , IOCTL_APP_INIT , &hEvent , sizeof(hEvent) , NULL , NULL , &Ret , NULL );
	if( !err )
	{
		MessageBox( NULL , "Can't Send Request to driver!" , "Error:" , MB_ICONERROR );
		return 0;
	}
	DialogBoxParam( NULL , MAKEINTRESOURCE(IDD_DIALOG1) , 0 , SpyDialogProc , 0 );
	return 0;
}








